package dispatcher.person.gui.state;

import java.util.Hashtable;
import java.util.Set;

import state.Globals;
import state.group.events.BaseEvent;
import state.group.events.EventCollection;
import state.group.events.EventType;
import state.person.Person;
import state.person.PersonState;
import state.person.events.BasePersonEvent;
import state.person.events.GoingInEvent;
import state.person.events.PersonRegisterEvent;

/**
 * This class store the collection of people that are in the elevator system
 * @author Caleb
 *
 */
public class PersonDataCollection extends Hashtable<String, Person>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 3334659176033504014L;

	private Hashtable<String, String> personCollectionInfo;
	
	/**
	 * The main constructor
	 */
	public PersonDataCollection(){
		personCollectionInfo = new Hashtable<String, String>();
	}
	
	private void updateCollectionInfo(String name, Person newState){
		String s = "";
		s += "\tType -> " + newState.getType() + "\n";
		s += "\tState -> " + newState.getState() + "\n";
		s += "\tSource -> " + newState.getHallCall().getFloor() + "\n";
		s += "\tDest -> " + newState.getDestination() + "\n";
		s += "\tElevator -> " + newState.getCurrentElevatorId(); 
		 
		
		synchronized(personCollectionInfo){
			
			personCollectionInfo.put(name, s);
		}
	}

	public synchronized void resetTextCollection(){
		personCollectionInfo.clear();
	}
	
	public String getPersonCollectionInfo(){
		String s = "";
		synchronized(personCollectionInfo){
			Set<String> names = personCollectionInfo.keySet();
			for(String n : names){
				s += n + "\n";
				s += personCollectionInfo.get(n) + "\n\n";  
			}
		}
		return s;
	}
	
	/**
	 * This method will update the local copy of all the people in the system
	 * based on the events given
	 * @param collection The collection of events to be looked at
	 */
	public synchronized void updateStructUsingEvents(EventCollection collection){
		
		for (BaseEvent e : collection){
			
			if (e instanceof BasePersonEvent){
				Globals.getLogger().log("Person Event is : " + e.getEventType(), this.getClass().getName(), "updateStructUsingEvents");
				Person p = null;
				String compName = ((BasePersonEvent) e).getPersonId().toString();
				p = this.get(compName);
				
				if (p == null){
					if (e.getEventType() != EventType.PersonRegisterEvent){
						Globals.getLogger().error("Event " + e.getEventType() + " was received instead of PersonRegisterEvent");
						continue;
					}
					p = ((PersonRegisterEvent)e).getPerson();
					this.put(p.getName(), p);
					updateCollectionInfo(p.getName(), p);
				}
				
				
				switch (e.getEventType())
		        {
		            case DestinationEvent:
		                p.setState(PersonState.atDestination);
		                updateCollectionInfo(p.getName(), p);
		                this.remove(p.getName());
		                break;
		            case GoingOutEvent:
		                p.setState(PersonState.goingOut);
		                updateCollectionInfo(p.getName(), p);
		                break;
		            case InsideEvent:
		                p.setState(PersonState.inside);
		                updateCollectionInfo(p.getName(), p);
		                break;
		            case GoingInEvent:
		                p.setState(PersonState.goingIn);
		                byte eleId = ((GoingInEvent) e).getElevatorId();
		                p.setCurrentElevatorId(eleId);
		                updateCollectionInfo(p.getName(), p);
		                break;
		            case WaitingEvent:
		                p.setState(PersonState.waiting);
		                updateCollectionInfo(p.getName(), p);
		                break;
		        }
			}
		}
	}
	
}
